﻿//-----------------------------------------------------------------------
// <copyright file="WebTumblrClient.cs" company="OpenSource">
//     All code is Microsoft Public License (Ms-PL)
// </copyright>
// <history>
// 2013.02  Created         Chris Hand
// </history>
//-----------------------------------------------------------------------
namespace OpenSource.TumblrAPI.ApiV2
{
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Text;
    using OpenSource.TumblrAPI.Exceptions;
    using OpenSource.TumblrAPI.Interfaces;

    /// <summary>
    /// Responsible for communicating with Tumblr over the internets.
    /// </summary>
    public class WebTumblrClient : ITumblrClient
    {
        /// <summary>
        /// Initializes a new instance of the WebTumblrClient class
        /// </summary>
        /// <param name="baseAddress">The base address of the tumblr server.  Always include a trailing '/'.</param>
        /// <param name="apiKey">The API key to add to every call</param>
        public WebTumblrClient(Uri baseAddress, string apiKey)
        {
            // We want to make sure it comes in as a valid URI, but we will always use it as a string.
            this.Address = baseAddress.ToString();
            this.ApiKey = apiKey;
        }

        /// <summary>
        /// Gets or sets the base address of the tumblr web api
        /// </summary>
        protected string Address { get; set; }

        /// <summary>
        /// Gets or sets the api key to add to every call
        /// </summary>
        protected string ApiKey { get; set; }

        /// <summary>
        /// Request information from the Tumblr server.  Takes the command and arguments and formats the command to send.
        /// </summary>
        /// <param name="command">The command to add onto the base address</param>
        /// <param name="args">The arguments to add on to the call</param>
        /// <returns>The raw response.</returns>
        public string Request(string command, IDictionary<string, object> args)
        {
            command = this.BuildCommand(command, args);
            return this.CallServer(command);
        }

        /// <summary>
        /// Converts the command and parameters into a command that can be sent over the web
        /// </summary>
        /// <param name="command">The command to format</param>
        /// <param name="args">The arguments to attach</param>
        /// <returns>The command to send</returns>
        protected virtual string BuildCommand(string command, IDictionary<string, object> args)
        {
            StringBuilder cmdbldr = new StringBuilder(this.Address);
            cmdbldr.Append(command);

            foreach (string arg in args.Keys)
            {
                cmdbldr.AppendFormat("{0}={1}&", arg, args[arg]);
            }

            cmdbldr.AppendFormat("api_key={0}", this.ApiKey);
            return cmdbldr.ToString();
        }

        /// <summary>
        /// Calls the server with the specified command
        /// </summary>
        /// <param name="command">The command send</param>
        /// <returns>The response of the command</returns>
        protected virtual string CallServer(string command)
        {
            WebClient client = new WebClient();
            string result = null;
            try
            {
                result = client.DownloadString(command);
            }
            catch (WebException we)
            {
                if (we.Message.Contains("The remote server returned an error: (401) Unauthorized."))
                {
                    throw new TumblrUnauthorizedException();
                }
                else
                {
                    throw new TumblrApiException("An unexpected error occurred while talking to the tumblr server.", we);
                }
            }

            return result;
        }
    }
}
